package defectsim.integrator.velocitylaw;

import javax.vecmath.Vector2d;

import repast.simphony.parameter.Parameters;

import defectsim.Globals;
import defectsim.SimulationEnvironment;
import defectsim.agents.Dislocation;
import defectsim.material.Material;

public class ThermallyActivatedVelocity implements VelocityLaw{

	private SimulationEnvironment environment = SimulationEnvironment.getInstance();
	private double temperature;
	
	public ThermallyActivatedVelocity(){
		Parameters p = environment.getParameters();
		this.temperature = (Double)p.getValue("temperature");	
	}
	
	@Override
	public Vector2d getVelocity(Dislocation dislocation, Vector2d force) {
		Material material = environment.getMaterial();
		
		double oneOverkT = 1.0 / Globals.BOLTZMAN_CONSTANT / temperature;
		double p = 0.757;
		double q = 1.075;
		double appliedWork = 0.0;
		
		// calculate glide velocity
		if (Math.abs(dislocation.getEffectiveStress().x) > material.getEffectiveStressAtZero())
		    appliedWork = material.getActivationEnergyAtZero();
		else {
			double stressRatio = Math.abs(dislocation.getEffectiveStress().x) / material.getEffectiveStressAtZero();
		    appliedWork = material.getActivationEnergyAtZero() * (1 - Math.pow((1 - Math.pow(stressRatio, p)), q));
		}
		double glideVelocity = material.getConstantVelocity() * 
				(Math.exp(-oneOverkT * (material.getActivationEnergyAtZero() - appliedWork)) - 
				 Math.exp(-oneOverkT * (material.getActivationEnergyAtZero() + appliedWork)));
		
		// calculate climb velocity
		
//		double climbVelocity = material.getConstantVelocity() * (dislocation.getEffectiveStress().x / material.getShearModulus()); 
//		double climbVelocity = force.y / environment.getMaterial().getDampingCoefficientForClimb();
//		double climbVelocity = glideVelocity * 1;
		if (Math.abs(dislocation.getEffectiveStress().y) > material.getEffectiveStressAtZero())
		    appliedWork = material.getActivationEnergyAtZero();
		else {
			double stressRatio = Math.abs(dislocation.getEffectiveStress().x) / material.getEffectiveStressAtZero();
		    appliedWork = material.getActivationEnergyAtZero() * (1 - Math.pow((1 - Math.pow(stressRatio, p)), q));
		}
		double climbVelocity = material.getConstantVelocity() * 
				(Math.exp(-oneOverkT * (material.getActivationEnergyAtZero() - appliedWork)) - 
				 Math.exp(-oneOverkT * (material.getActivationEnergyAtZero() + appliedWork)));
		
		return new Vector2d(Math.signum(dislocation.getEffectiveStress().x) * 
				Math.signum(dislocation.getUnitBurgersVector()) * glideVelocity, 
				Math.signum(dislocation.getEffectiveStress().x) * 
				Math.signum(dislocation.getUnitBurgersVector()) * climbVelocity);
	}

}
